=begin

This file is part of the RSIF project, http://rsif.googlecode.com

Copyright (c) 2009-2009 Roberto Dario Seminara <robertodarioseminara@gmail.com>

rsif is free software: you can redistribute it and/or modify
it under the terms of the gnu general public license as published by
the free software foundation, either version 3 of the license, or
(at your option) any later version.

rsif is distributed in the hope that it will be useful,
but without any warranty; without even the implied warranty of
merchantability or fitness for a particular purpose.  see the
gnu general public license for more details.

you should have received a copy of the gnu general public license
along with rsif.  if not, see <http://www.gnu.org/licenses/>.
=end

require "find"
require "context"
require "modules/cmd_handler"
require "modules/module"
require "modules/provideinfo"
require "logger/contextlogger"
require "cmd_dispatcher"
require "locale"

module Rsif
module Core

##
#	Framework es un Facade (o fachada) que encapsula la operacion sobre el framework, exceptuando
#	alugunos manejos que se puedan hacer sobre el framework
##
class Framework
	include Rsif::Core::Logging

	LocalePath = "data/locale/"

	attr_accessor	:cmd_handlers




	##
	#	Inicializa el framework, por ahora solo configura el logger
	##
	def initialize
		load_module_path(LocalePath)
		logger.level = 2
		cmd_handler.framework = self
	end

	##
	#	Carga todos los modulos .rb que pueda encontrar bajo el path especifico
	#
	#	=== Examples
	#
	#	framework.load_module_path("base")
	#	framework.load_module_path("plugin")
	##
	def load_module_path( path )
		::Find.find(path) do |file|
			case file
				when /\.rb$/
				# cargar el archivo
				#logger.debug "cargando modulo #{file}"
				load_ruby_from_file(file) do |klass|

					a = Rsif::Core::Modules::ProvideInfo
					a.instance.registry_class_module( file.sub(".rb",""), klass )

#"loaded class module #{klass} from #{file}"
					logger.debug { Locale.load_class_module_from(klass,file)  }
				end #do
				when /\.locale$/
					logger.debug { Locale.load_locale_module_from(file) }

					Rsif::Core::Localization::Manager.instance.add_locale_module(file)
			
			end
		end

		# actualizar handlers
		cmd_handler.update_handlers
		cmd_handler.framework = self

		
	end

	##
	#
	#	Ejecuta un comando sobre el framework, recibe cualquier cantidad de argumentos
	#	para el comando
	#
	#	=== Examples
	#
	#	framework.run_command("load_module_path", "base")
	#
	##
	def run_command( command_name, *args )
		cmd_handler.run_command( command_name, *args)		
	end

	##
	#	Instancia un modulo por nombre o por objeto-clase, ejecuta todos los modulos
	#	dependientes y obtiene los parametros necesarios para 
	#	instanciarlo
	##
	def instanciate( module_spec, params = nil )

		
		if module_spec.class == String then
			mod = Rsif::Core::Modules::ProvideInfo.instance.module_from_name( module_spec )
		else
			mod = module_spec
		end

		instance = nil

		if mod.can_instantiate then
			logger.info { Locale.instanciate_module(module_spec) }
			instance = mod.create(params)

			begin
			instance.framework = self
			rescue
			end
		else

			mod.dependencies.each do |dep|
				providers = provideinfo.providers(dep)

				logger.debug { Locale.provider_of_dep(dep,providers.join(", ")) }

				providers.each do |prov|
					ins = self.instanciate(prov)
					ins.run
				end
			end

			if mod.can_instantiate then
				instance = mod.create(params)

				begin
				instance.framework = self
				rescue
				end
			else
				logger.error { Locale.failed_to_instantiate(module_spec) }
			end
		end		
=begin
		if mod
			logger.info { Locale.instanciate_module(module_spec) }

			unless mod.can_instantiate
				mod.dependencies.each do |dep|
					if context.symbol(dep) == nil
					  # ejecuta los modulos que proveen el simbolo hasta 
					  # obtenerlo
					  providers = provideinfo.providers(dep)

					  logger.debug { Locale.provider_of_dep(dep,providers.join(", ")) }

					  providers.each do |prov|
					      begin

						ins = self.instanciate(prov)
						ins.run
#						if prov.can_instantiate
#						  prov.create.run
#						end
					      rescue Exception => e
						  logger.warn { Locale.run_exception(e,prov) }
					      end
					  end
					end
				end
			end

			if mod.can_instantiate
				instance = mod.create
			else
				logger.error { Locale.failed_to_instantiate(module_spec) }
			end
		else
			logger.error { Locale.failed_to_find(module_spec) } 
		end
=end
		instance
	end

	##
	#	Ejecuta todos los modulos que heredan del modulo o los modulos
	#	que proveen un simbolo determinado
	##
	def run_group( sym )

		self.provide_info.providers( sym ).each do |klass|
			logger.debug( Locale.running_module_group( klass.to_s ) )

			klass.each_class_match( context ) do |m_klass|
				logger.debug( Locale.running_module( m_klass.to_s ) )
				ins = m_klass.new
				ins.framework = self
				if block_given? then
					ins.run( context ) do |*x| yield(*x) end
				else
					ins.run( context )
				end
			end
		end
	end

	def provide_info
		Rsif::Core::Modules::ProvideInfo.instance
	end

	def context
		Rsif::Core::Context.instance
	end
private

	def provideinfo
		Rsif::Core::Modules::ProvideInfo.instance
	end

	def load_ruby_from_file( file )
		Rsif::Core::Modules::Module.module_load_proc = proc do |klass|
			yield(klass)
		end
		require file
	end

	def cmd_handler
		Context.instance.cmd_dispatcher
	end
end

end
end

